//! 指纹识别引擎模块
//! 提供Web服务指纹识别的实际执行逻辑

use anyhow::{anyhow, Result};
use futures::future::join_all;
use log::{debug, error, info, warn};
use chrono::Utc;
use reqwest::{Client, Response};
use std::collections::HashSet;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::Semaphore;
use tokio::time::timeout;

use super::fingerprint_core::{FingerprintCoreEngine, FingerprintInfo, FingerprintResult, ResponseInfo};

/// 指纹识别引擎插件结构定义
#[derive(Debug, Clone)]
pub struct FingerprintEnginePlugin {
    /// 插件名称
    pub name: String,
    /// 支持的端口列表
    pub ports: Vec<u16>,
    /// 支持的扫描模式
    pub modes: Vec<String>,
    /// 指纹规则目录路径
    pub rule_dir: String,
    /// 超时时间（秒）
    pub timeout_seconds: u64,
    /// 并发工作线程数
    pub workers: usize,
    /// HTTP客户端
    pub client: Client,
    /// 指纹识别核心引擎
    pub core_engine: FingerprintCoreEngine,
    /// 常见指纹识别路径
    pub common_paths: Vec<String>,
}

impl FingerprintEnginePlugin {
    /// 创建新的指纹识别引擎插件实例
    pub fn new() -> Result<Self> {
        // 优先使用./rules/finger目录，如果不存在则使用./fingerprint_rules
        let mut default_rule_dir = "./rules/finger";
        
        // 如果rules/finger目录不存在，则使用fingerprint_rules目录
        if !std::path::Path::new(default_rule_dir).exists() {
            default_rule_dir = "./fingerprint_rules";
            
            // 检查默认规则目录是否存在，如果不存在则创建
            if !std::path::Path::new(default_rule_dir).exists() {
                match std::fs::create_dir_all(default_rule_dir) {
                    Ok(_) => info!("[Fingerprint] Created default fingerprint rule directory: {}", default_rule_dir),
                    Err(e) => warn!("[Fingerprint] Failed to create default fingerprint rule directory: {}", e),
                }
            }
        } else {
            info!("[Fingerprint] Using fingerprint rules from: {}", default_rule_dir);
        }
        
        // 常见的指纹识别路径
        let common_paths = vec![
            "/", 
            "/robots.txt", 
            "/sitemap.xml", 
            "/favicon.ico",
            "/.git/HEAD", // 检测git泄露
            "/.env",      // 检测环境变量泄露
            "/admin",     // 检测管理后台
            "/login",     // 检测登录页面
            "/wp-admin",  // WordPress特征
            "/wp-content",
            "/joomla",    // Joomla特征
            "/drupal",    // Drupal特征
            "/phpinfo.php", // PHP信息页面
            "/.well-known/security.txt",
            "/.well-known/change-password",
        ];
        
        Ok(Self {
            name: "fingerprint".to_string(),
            ports: vec![80, 443, 8080, 8443],
            modes: vec!["http", "https", "web"].iter().map(|s| s.to_string()).collect(),
            rule_dir: default_rule_dir.to_string(),
            timeout_seconds: 10,
            workers: 10,
            client: Client::builder()
                .timeout(Duration::from_secs(10))
                .danger_accept_invalid_certs(true) // 允许自签名证书，用于MITM场景
                .build()?,
            core_engine: FingerprintCoreEngine::new(),
            common_paths: common_paths.iter().map(|s| s.to_string()).collect(),
        })
    }

    /// 配置规则目录
    pub fn with_rule_dir(mut self, rule_dir: &str) -> Result<Self> {
        if !std::path::Path::new(rule_dir).exists() || !std::path::Path::new(rule_dir).is_dir() {
            return Err(anyhow!("Rule directory does not exist or is not a directory: {}", rule_dir));
        }
        
        self.rule_dir = rule_dir.to_string();
        Ok(self)
    }

    /// 配置超时时间
    pub fn with_timeout(mut self, timeout_seconds: u64) -> Self {
        self.timeout_seconds = timeout_seconds;
        // 同时更新HTTP客户端的超时设置
        self.client = Client::builder()
            .timeout(Duration::from_secs(timeout_seconds))
            .danger_accept_invalid_certs(true)
            .build()
            .unwrap_or_else(|_| self.client.clone());
        self
    }

    /// 配置并发工作线程数
    pub fn with_workers(mut self, workers: usize) -> Self {
        self.workers = workers;
        self
    }

    /// 配置自定义指纹识别路径
    pub fn with_custom_paths(mut self, paths: Vec<String>) -> Self {
        self.common_paths = paths;
        self
    }

    /// 加载指纹规则
    pub async fn load_rules(&mut self) -> Result<()> {
        info!("[Fingerprint] Loading fingerprint rules from: {}", self.rule_dir);
        self.core_engine.load_rules_from_dir(&self.rule_dir)?;
        
        if self.core_engine.rules.is_empty() {
            warn!("[Fingerprint] No fingerprint rules loaded from directory. Trying alternative rule sources.");
            // 尝试加载finger.json规则
            let finger_json_path = "./rules/finger/finger.json";
            if std::path::Path::new(finger_json_path).exists() {
                info!("[Fingerprint] Found finger.json rules, loading...");
                self.core_engine.load_rule_from_json(finger_json_path)?;
            } else {
                warn!("[Fingerprint] No finger.json rules found. Using minimal built-in rules.");
                self.load_minimal_rules();
            }
        }
        
        Ok(())
    }
    
    /// 加载finger.json规则
    pub fn load_finger_json(&mut self, file_path: &str) -> Result<()> {
        self.core_engine.load_rule_from_json(file_path)
    }

    /// 加载最小化的内置规则（当没有外部规则时使用）
    fn load_minimal_rules(&mut self) {
        // 这里可以定义一些内置的基础规则
        // 由于没有文件系统访问，我们可以直接在代码中创建一些简单规则
    }

    /// 发送HTTP请求并返回响应
    async fn send_request(&self, url: &str) -> Result<Response> {
        debug!("[Fingerprint] Sending fingerprint request to: {}", url);
        
        let response = timeout(
            Duration::from_secs(self.timeout_seconds),
            self.client.get(url)
                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
                .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
                .header("Accept-Language", "en-US,en;q=0.5")
                .send()
        ).await??;
        
        Ok(response)
    }

    /// 从响应中提取指纹信息
    async fn extract_fingerprints(&self, response: Response) -> Vec<FingerprintInfo> {
        // 先获取URL，它不消费Response
        let url = response.url().to_string();
        
        // 先获取状态码
        let status = response.status().as_u16();
        
        // 获取headers引用（但先保存为字符串格式，因为text()会消费Response）
        let headers_map = response.headers().clone();
        
        // text()会消费整个Response，所以最后调用
        let body = response.text().await.unwrap_or_default();
        
        let response_info = self.core_engine.parse_response(status, &headers_map, &body, &url);
        self.core_engine.identify_fingerprints(&response_info)
    }

    /// 对单个URL路径执行指纹识别
    async fn identify_path(&self, base_url: &str, path: &str) -> Result<Vec<FingerprintInfo>> {
        let full_url = if path.starts_with("/") {
            format!("{}{}", base_url.trim_end_matches('/'), path)
        } else {
            format!("{}/{}", base_url.trim_end_matches('/'), path)
        };
        
        match self.send_request(&full_url).await {
            Ok(response) => {
                let fingerprints = self.extract_fingerprints(response).await;
                if !fingerprints.is_empty() {
                    info!("[Fingerprint] Identified {} technologies on {}", fingerprints.len(), full_url);
                    // 添加更详细的指纹识别结果日志
                    for fingerprint in &fingerprints {
                        debug!("[Fingerprint] Found technology: {} (version: {:?})",
                               fingerprint.name, fingerprint.version);
                    }
                }
                Ok(fingerprints)
            },
            Err(e) => {
                debug!("[Fingerprint] Failed to request {}: {}", full_url, e);
                Ok(Vec::new()) // 请求失败时返回空列表
            }
        }
    }

    /// 对目标URL执行完整的指纹识别
    pub async fn identify(&mut self, target: &str) -> Result<FingerprintResult> {
        info!("[Fingerprint] Starting fingerprint identification against target: {}", target);
        let start_time = Instant::now();
        
        // 确保目标URL格式正确
        let target = if !target.starts_with("http://") && !target.starts_with("https://") {
            format!("http://{}", target)
        } else {
            target.to_string()
        };
        
        // 使用信号量控制并发
        let semaphore = Arc::new(Semaphore::new(self.workers));
        let mut tasks = Vec::new();
        
        // 为每个常见路径创建一个异步任务
        for path in &self.common_paths {
            let target = target.clone();
            let path = path.clone();
            let semaphore = Arc::clone(&semaphore);
            let engine = self.clone();
            
            tasks.push(tokio::spawn(async move {
                let _permit = semaphore.acquire().await.unwrap();
                engine.identify_path(&target, &path).await
            }));
        }
        
        // 等待所有任务完成
        let results = join_all(tasks).await;
        
        // 收集所有识别结果，去重
        let mut all_technologies = HashSet::new();
        for result in results {
            if let Ok(technologies) = result {
                for tech in technologies {
                    all_technologies.insert(tech);
                }
            }
        }
        
        // 转换为Vec
        // Flatten the HashSet<Vec<FingerprintInfo>> into Vec<FingerprintInfo>
        let technologies: Vec<FingerprintInfo> = all_technologies.into_iter().flatten().collect();
        
        let elapsed = start_time.elapsed();
        info!("[Fingerprint] Identification completed in {:?}. Identified {} technologies.", 
              elapsed, technologies.len());
        // 添加识别结果的详细日志
        if !technologies.is_empty() {
            debug!("[Fingerprint] Detailed results for {}:", target);
            for tech in &technologies {
                debug!("[Fingerprint] - {} (version: {:?})",
                       tech.name, tech.version);
            }
        } else {
            debug!("[Fingerprint] No technologies identified for {}", target);
        }
        
        // 格式化当前时间
        let now = chrono::Utc::now();
        let identified_at = now.format("%Y-%m-%d %H:%M:%S UTC").to_string();
        
        Ok(FingerprintResult {
            target,
            technologies,
            identified_at,
        })
    }

    /// 快速指纹识别（仅检查根路径）
    pub async fn quick_identify(&mut self, target: &str) -> Result<FingerprintResult> {
        info!("[Fingerprint] Starting quick identification against target: {}", target);
        let start_time = Instant::now();
        
        // 确保目标URL格式正确
        let target = if !target.starts_with("http://") && !target.starts_with("https://") {
            format!("http://{}", target)
        } else {
            target.to_string()
        };
        
        // 仅检查根路径
        let technologies = match self.identify_path(&target, "/").await {
            Ok(techs) => techs,
            Err(e) => {
                warn!("[Fingerprint] Quick identification failed: {}", e);
                Vec::new()
            }
        };
        
        let elapsed = start_time.elapsed();
        info!("[Fingerprint] Quick identification completed in {:?}. Identified {} technologies.", 
              elapsed, technologies.len());
        // 添加快速识别结果的详细日志
        if !technologies.is_empty() {
            debug!("[Fingerprint] Quick results for {}:", target);
            for tech in &technologies {
                debug!("[Fingerprint] - {} (version: {:?})",
                       tech.name, tech.version);
            }
        } else {
            debug!("[Fingerprint] No technologies identified in quick scan for {}", target);
        }
        
        // 格式化当前时间
        let now = chrono::Utc::now();
        let identified_at = now.format("%Y-%m-%d %H:%M:%S UTC").to_string();
        
        Ok(FingerprintResult {
            target,
            technologies,
            identified_at,
        })
    }

    /// 从已有的HTTP响应中识别指纹（用于与MITM代理集成）
    pub fn identify_from_response(&self, status: u16, headers: &http::HeaderMap, body: &str, url: &str) -> Vec<FingerprintInfo> {
        debug!("[Fingerprint] Identifying from HTTP response: {} (status: {})", url, status);
        let response_info = self.core_engine.parse_response(status, headers, body, url);
        let fingerprints = self.core_engine.identify_fingerprints(&response_info);
        
        // 添加识别结果日志
        if !fingerprints.is_empty() {
            info!("[Fingerprint] Identified {} technologies from response: {}", fingerprints.len(), url);
            for fingerprint in &fingerprints {
                debug!("[Fingerprint] - {} (version: {:?})",
                       fingerprint.name, fingerprint.version);
            }
        } else {
            debug!("[Fingerprint] No technologies identified from response: {}", url);
        }
        
        fingerprints
    }
    
    /// 从HTTP响应中识别指纹并返回结果对象
    pub fn identify_from_http_response(&self, response: &http::Response<Vec<u8>>, request_url: Option<&str>) -> Result<FingerprintResult> {
        info!("[Fingerprint] Processing HTTP response for fingerprint identification");
        // 提取响应内容
        let status_code = response.status().as_u16();
        let headers = response.headers();
        
        // 将body转换为字符串
        let body_str = String::from_utf8_lossy(response.body()).to_string();
        let url = request_url.unwrap_or("");
        
        // 使用现有的识别方法
        let technologies = self.identify_from_response(status_code, headers, &body_str, url);
        
        // 格式化当前时间
        let now = chrono::Utc::now();
        let identified_at = now.format("%Y-%m-%d %H:%M:%S UTC").to_string();
        
        Ok(FingerprintResult {
            target: url.to_string(),
            technologies,
            identified_at,
        })
    }
    
    /// 计算favicon哈希值（用于匹配finger.json中的faviconhash规则）
    pub fn calculate_favicon_hash(data: &[u8]) -> String {
        // 实现favicon哈希计算算法
        let hash: u64 = data.iter().fold(0, |acc, &x| acc.wrapping_mul(16777619).wrapping_add(x as u64));
        format!("{}", hash)
    }
}